using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;
using Oracle.DataAccess.Client;

namespace GS1.DataAccess
{
    /// <summary>
    /// <para>Clase       : DataBase</para>
    /// <para>Descripcion : Permite operar con BD Oracle de manera nativa</para>
    /// <para>Autor       : Pedro Miguel Vera Rafael</para>
    /// <para>Fecha       : 15/06/2011</para>
    /// <para>Empresa     : GS1 Peru</para>
    /// </summary>
    public class Database : IDisposable
    {
        #region --- Variables ---
        private OracleConnection conexion = null;
        private OracleCommand comando = null;
        private OracleDataAdapter adap = null;
        #endregion

        #region --- Constructor y Destructor ---
        public Database(ConstantesDAO.NombreInterface nombreInterface)
        {
            this.conexion = new OracleConnection(DataBaseHelper.obtenerDbCadenaConexion(nombreInterface.ToString()));
        }

        public void Dispose()
        {
            if (this.conexion != null) { this.conexion.Dispose(); }
            this.conexion = null;

            if (this.comando != null) { this.comando.Dispose(); }
            this.comando = null;

            if (this.adap != null) { this.adap.Dispose(); }
            this.adap = null;

            GC.SuppressFinalize(this);
            GC.Collect();
        }

        ~Database()
        {
            this.Dispose();
        }

        #endregion

        #region --- Metodos Transaccion ---
        public void iniciarTransaccion()
        {
            if (this.comando == null)
            {
                this.comando = new OracleCommand();
            }

            if (this.conexion.State == ConnectionState.Closed) { this.abrir(); }

            this.comando.Connection = this.conexion;
            this.comando.CommandType = CommandType.StoredProcedure;
            this.comando.CommandText = string.Empty;
            this.comando.Connection.BeginTransaction();
        }

        public void confirmarTransaccion()
        {
            if (this.comando != null)
            {
                this.comando.Transaction.Commit();
            }
        }
        #endregion

        #region --- Metodos Conexion ---
        public void abrir()
        {
            this.conexion.Open();
        }

        public void cerrar()
        {
            this.conexion.Close();
        }
        #endregion

        #region --- Propiedades y Metodos Propios ---
        public string TextoSQL
        {
            set
            {
                if (this.comando == null)
                {
                    this.comando = new OracleCommand();
                }

                if (this.conexion.State == ConnectionState.Closed) { this.abrir(); }

                this.comando.Connection = this.conexion;
                this.comando.CommandType = CommandType.Text;
                this.comando.CommandText = value;
            }
        }

        public string NombreProcedimiento
        {
            set
            {
                if (this.comando == null)
                {
                    this.comando = new OracleCommand();
                }

                if (this.conexion.State == ConnectionState.Closed) { this.abrir(); }

                this.comando.Connection = this.conexion;
                this.comando.CommandType = CommandType.StoredProcedure;
                this.comando.CommandText = value;
                this.comando.Parameters.Clear();
            }
        }

        public void agregarParametro(string nombreParametro, DbType tipoParametro, ParameterDirection direccionParametro)
        {
            if (this.comando != null)
            {
                OracleParameter parametro = new OracleParameter();
                parametro.ParameterName = nombreParametro;
                parametro.DbType = tipoParametro;
                parametro.Direction = direccionParametro;

                establecerTipoParametroOracle(parametro);

                this.comando.Parameters.Add(parametro);
            }
        }

        public void agregarParametro(string nombreParametro, DbType tipoParametro, ParameterDirection direccionParametro, Object valorParametro)
        {
            if (comando != null)
            {
                OracleParameter parametro = new OracleParameter();
                parametro.ParameterName = nombreParametro;

                parametro.DbType = tipoParametro;

                parametro.Direction = direccionParametro;
                parametro.Value = valorParametro;

                establecerTipoParametroOracle(parametro);

                this.comando.Parameters.Add(parametro);
            }
        }

        public void agregarParametro(string nombreParametro, DbType tipoParametro, ParameterDirection direccionParametro, Object valorParametro, int tamanioParametro)
        {
            if (comando != null)
            {
                OracleParameter parametro = new OracleParameter();
                parametro.ParameterName = nombreParametro;
                parametro.DbType = tipoParametro;
                parametro.Direction = direccionParametro;
                parametro.Value = valorParametro;
                parametro.Size = tamanioParametro;

                establecerTipoParametroOracle(parametro);

                this.comando.Parameters.Add(parametro);
            }
        }

        private void establecerTipoParametroOracle(OracleParameter parametro)
        {
            switch (parametro.DbType)
            {
                case DbType.Binary:
                    ((OracleParameter)parametro).OracleDbType = OracleDbType.RefCursor;
                    break;
                //case DbType.Binary:
                //    ((OracleParameter)parametro).OracleDbType = OracleDbType.Blob;
                //    break;
            }
        }

        public OracleParameter obtenerParametro(string nombreParametro)
        {
            if (comando != null)
            {
                return comando.Parameters[nombreParametro];
            }
            return null;
        }

        public IDataReader obtenerDataReader()
        {
            return this.comando.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection);
        }

        public IDataAdapter obtenerDataAdapter()
        {
            if (this.adap == null)
            {
                this.adap = new OracleDataAdapter();
            }

            //if (this.conexion == null) { this.abrir(); }

            this.adap.SelectCommand = this.comando;

            return adap;
        }

        public int ejecutar()
        {
            int resultado = this.comando.ExecuteNonQuery();
            resultado = resultado < 0 ? resultado * -1 : resultado;
            return resultado;
        }

        public object ejecutarEscalar()
        {
            return this.comando.ExecuteScalar();
        }
        #endregion
    }
}